﻿using Microsoft.Win32;
using SkiaSharp;
using SkiaSharp.Views.WPF;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using X.Infrastructure.Shapes;
using X.Infrastructure.WPF.Extends;
using X.WPF.Controls.CustomControls;
using X.WPF.Controls.Enums;
using X.WPF.Controls.EventArgs.CanvasShapeArgs;
using X.WPF.Controls.EventArgs.DraggableControlArgs;
using Brush = System.Windows.Media.Brush;
using Brushes = System.Windows.Media.Brushes;
using Color = System.Windows.Media.Color;

namespace X.WPF.Controls.UserControls
{
    /// <summary>
    /// 图片画布
    /// </summary>
    public partial class ImageCanvas : UserControl
    {

        #region # 字段及构造器

        /// <summary>
        /// 默认画笔颜色
        /// </summary>
        private static readonly Brush _defaultStroke;

        /// <summary>
        /// 默认填充颜色
        /// </summary>
        private static readonly Brush _defaultFill;

        /// <summary>
        /// 默认选中颜色
        /// </summary>
        private static readonly Brush _defaultSelectedShapeColor;

        /// <summary>
        /// 图片画布拖拽组件
        /// </summary>
        private DraggableControl _mainCanvasDraggable;

        /// <summary>
        /// 缩放系数
        /// </summary>
        private double _scale;

        /// <summary>
        /// 起始点
        /// </summary>
        private PointX _startPoint;

        /// <summary>
        /// 型状原始颜色
        /// </summary>
        private Brush _shapeOriginalColor;

        /// <summary>
        /// 型状原始填充色
        /// </summary>
        private Brush _shapeOriginalFill;

        /// <summary>
        /// 型状原始粗细
        /// </summary>
        private double _shapeOriginalThickness;

        /// <summary>
        /// 原型状
        /// </summary>
        private ShapeX _oldShape;

        /// <summary>
        /// 新型状
        /// </summary>
        private ShapeX _newShape;

        /// <summary>
        /// 是否绘制中
        /// </summary>
        private bool _isDrawing;

        /// <summary>
        /// 是否拖拽中
        /// </summary>
        private bool _isDraging;

        /// <summary>
        /// 型状控件列表
        /// </summary>
        private readonly ObservableCollection<CanvasShape> _canvasShapes;

        /// <summary>
        /// 静态构造器
        /// </summary>
        static ImageCanvas()
        {
            // 设置默认值
            ImageCanvas._defaultStroke = Brushes.Red;
            ImageCanvas._defaultFill = Brushes.Transparent;
            ImageCanvas._defaultSelectedShapeColor = Brushes.Orange;

            // 注册依赖属性
            ImageCanvas.TitleProperty = DependencyProperty.Register(nameof(ImageCanvas.Title), typeof(string), typeof(ImageCanvas), new PropertyMetadata("图片"));
            ImageCanvas.UseModelProperty = DependencyProperty.Register(nameof(ImageCanvas.UseModel), typeof(CanvasUseMode), typeof(ImageCanvas), new PropertyMetadata(CanvasUseMode.Nomal, ImageCanvas.OnUseModelChanged));
            ImageCanvas.OperatorModelProperty = DependencyProperty.Register(nameof(ImageCanvas.OperatorModel), typeof(CanvasOperatorMode), typeof(ImageCanvas), new PropertyMetadata(CanvasOperatorMode.Nomal, ImageCanvas.OnOperatorModelChanged));
            ImageCanvas.DrawTypeProperty = DependencyProperty.Register(nameof(ImageCanvas.DrawType), typeof(CanvasShapeType), typeof(ImageCanvas), new PropertyMetadata(CanvasShapeType.Rectangle, ImageCanvas.OnDrawTypeChanged));
            ImageCanvas.ImageScalePropertyKey = DependencyProperty.RegisterReadOnly(nameof(ImageCanvas.ImageScale), typeof(double), typeof(ImageCanvas), new PropertyMetadata(1d));
            ImageCanvas.ImageScaleProperty = ImageCanvas.ImageScalePropertyKey.DependencyProperty;
            ImageCanvas.ImageSourceProperty = DependencyProperty.Register(nameof(ImageCanvas.ImageSource), typeof(ImageSource), typeof(ImageCanvas), new PropertyMetadata(null, ImageCanvas.OnImageSourceChanged));
            ImageCanvas.StrokeProperty = DependencyProperty.Register(nameof(ImageCanvas.Stroke), typeof(Brush), typeof(ImageCanvas), new PropertyMetadata(ImageCanvas._defaultStroke));
            ImageCanvas.StrokeThicknessProperty = DependencyProperty.Register(nameof(ImageCanvas.StrokeThickness), typeof(double), typeof(ImageCanvas), new PropertyMetadata(2d));
            ImageCanvas.FillProperty = DependencyProperty.Register(nameof(ImageCanvas.Fill), typeof(Brush), typeof(ImageCanvas), new PropertyMetadata(ImageCanvas._defaultFill));
            ImageCanvas.SelectedShapeColorProperty = DependencyProperty.Register(nameof(ImageCanvas.SelectedShapeColor), typeof(Brush), typeof(ImageCanvas), new PropertyMetadata(ImageCanvas._defaultSelectedShapeColor));
            ImageCanvas.ShapeContextMenuProperty = DependencyProperty.Register(nameof(ImageCanvas.ShapeContextMenu), typeof(ContextMenu), typeof(ImageCanvas));
            ImageCanvas.ShapesProperty = DependencyProperty.Register(nameof(ImageCanvas.Shapes), typeof(ObservableCollection<ShapeX>), typeof(ImageCanvas), new PropertyMetadata(new ObservableCollection<ShapeX>(), ImageCanvas.OnShapesChanged));
            ImageCanvas.SelectedShapeProperty = DependencyProperty.Register(nameof(ImageCanvas.SelectedShape), typeof(ShapeX), typeof(ImageCanvas), new PropertyMetadata(null, ImageCanvas.OnSelectedShapeChanged));
            ImageCanvas.ShowToolBarProperty = DependencyProperty.Register(nameof(ImageCanvas.ShowToolBar), typeof(bool), typeof(ImageCanvas), new PropertyMetadata(true, ShowToolBarChangedCallback));
            ImageCanvas.IsCanDrawRectangleProperty = DependencyProperty.Register(nameof(ImageCanvas.IsCanDrawRectangle), typeof(bool), typeof(ImageCanvas), new PropertyMetadata(true, IsCanDrawRectangleChangedCallback));
            ImageCanvas.IsCanDrawCircleProperty = DependencyProperty.Register(nameof(ImageCanvas.IsCanDrawCircle), typeof(bool), typeof(ImageCanvas), new PropertyMetadata(true, IsCanDrawCircleChangedCallback));
            ImageCanvas.IsCanDrawPolygonProperty = DependencyProperty.Register(nameof(ImageCanvas.IsCanDrawPolygon), typeof(bool), typeof(ImageCanvas), new PropertyMetadata(true, IsCanDrawPolygonChangedCallback));
            ImageCanvas.IsCanDrawPolylineProperty = DependencyProperty.Register(nameof(ImageCanvas.IsCanDrawPolyline), typeof(bool), typeof(ImageCanvas), new PropertyMetadata(true, IsCanDrawPolylineChangedCallback));

            // 注册路由事件
            ImageCanvas._ShapeDrawnEvent = EventManager.RegisterRoutedEvent(nameof(ImageCanvas.ShapeDrawn), RoutingStrategy.Direct, typeof(RoutedEventHandler), typeof(ImageCanvas));
            ImageCanvas._SelectedShapeChangedEvent = EventManager.RegisterRoutedEvent(nameof(ImageCanvas.SelectedShapeChanged), RoutingStrategy.Direct, typeof(RoutedEventHandler), typeof(ImageCanvas));
            ImageCanvas._ShapeDragChangingEvent = EventManager.RegisterRoutedEvent(nameof(ImageCanvas.ShapeDragChanging), RoutingStrategy.Direct, typeof(RoutedEventHandler), typeof(ImageCanvas));
            ImageCanvas._ShapeDragCompletedEvent = EventManager.RegisterRoutedEvent(nameof(ImageCanvas.ShapeDragCompleted), RoutingStrategy.Direct, typeof(RoutedEventHandler), typeof(ImageCanvas));
            ImageCanvas._ShapeClickEvent = EventManager.RegisterRoutedEvent(nameof(ImageCanvas.ShapeClick), RoutingStrategy.Direct, typeof(RoutedEventHandler), typeof(ImageCanvas));

        }

        /// <summary>
        /// 构造器
        /// </summary>
        public ImageCanvas()
        {
            this.InitializeComponent();

            // 默认值
            this._canvasShapes = new ObservableCollection<CanvasShape>();
            this.OperatorModel = CanvasOperatorMode.Nomal;
            this.DrawType = CanvasShapeType.Rectangle;

            this.Render();
            this.OperatorModelChanged(this.OperatorModel);
        }

        #endregion

        #region # 依赖属性

        #region 标题 —— string TitleProperty

        /// <summary>
        /// 标题
        /// </summary>
        public static DependencyProperty TitleProperty;

        /// <summary>
        /// 标题
        /// </summary>
        public string Title
        {
            get => (string)base.GetValue(ImageCanvas.TitleProperty);
            set => base.SetValue(ImageCanvas.TitleProperty, value);
        }

        #endregion

        #region 使用模式 —— ImageCanvasUseModel UseModel

        /// <summary>
        /// 使用模式依赖属性
        /// </summary>
        public static DependencyProperty UseModelProperty;

        /// <summary>
        /// 使用模式
        /// </summary>
        public CanvasUseMode UseModel
        {
            get => (CanvasUseMode)base.GetValue(ImageCanvas.UseModelProperty);
            set => base.SetValue(ImageCanvas.UseModelProperty, value);
        }

        #endregion

        #region 操作模式 —— ImageCanvasOperatorModel OperatorModel

        /// <summary>
        /// 操作模式依赖属性
        /// </summary>
        public static DependencyProperty OperatorModelProperty;

        /// <summary>
        /// 操作模式
        /// </summary>
        public CanvasOperatorMode OperatorModel
        {
            get => (CanvasOperatorMode)base.GetValue(ImageCanvas.OperatorModelProperty);
            set => base.SetValue(ImageCanvas.OperatorModelProperty, value);
        }

        #endregion

        #region 绘制类型 —— CanvasShapeType DrawType

        /// <summary>
        /// 绘制类型依赖属性
        /// </summary>
        public static DependencyProperty DrawTypeProperty;

        /// <summary>
        /// 绘制类型依赖属性
        /// </summary>
        public CanvasShapeType DrawType
        {
            get => (CanvasShapeType)base.GetValue(ImageCanvas.DrawTypeProperty);
            set => base.SetValue(ImageCanvas.DrawTypeProperty, value);
        }

        #endregion

        #region 图片缩放系数 —— double ImageScale

        /// <summary>
        /// 图片缩放系数赖属性
        /// </summary>
        protected static DependencyPropertyKey ImageScalePropertyKey;

        /// <summary>
        /// 图片缩放系数赖属性
        /// </summary>
        public static DependencyProperty ImageScaleProperty;

        /// <summary>
        /// 图片缩放系数
        /// </summary>
        public double ImageScale => (double)base.GetValue(ImageCanvas.ImageScaleProperty);

        #endregion

        #region 图片源 —— ImageSource ImageSource

        /// <summary>
        /// 图片源依赖属性
        /// </summary>
        public static DependencyProperty ImageSourceProperty;

        /// <summary>
        /// 图片源
        /// </summary>
        public ImageSource ImageSource
        {
            get => (ImageSource)base.GetValue(ImageCanvas.ImageSourceProperty);
            set => base.SetValue(ImageCanvas.ImageSourceProperty, value);
        }

        #endregion

        #region 画笔颜色 —— Brush Stroke

        /// <summary>
        /// 画笔颜色依赖属性
        /// </summary>
        public static DependencyProperty StrokeProperty;

        /// <summary>
        /// 画笔颜色
        /// </summary>s
        public Brush Stroke
        {
            get => (Brush)base.GetValue(ImageCanvas.StrokeProperty);
            set => base.SetValue(ImageCanvas.StrokeProperty, value);
        }

        #endregion

        #region 画笔粗细 —— double StrokeThickness

        /// <summary>
        /// 画笔粗细赖属性
        /// </summary>
        public static DependencyProperty StrokeThicknessProperty;

        /// <summary>
        /// 画笔粗细
        /// </summary>
        public double StrokeThickness
        {
            get => (double)base.GetValue(ImageCanvas.StrokeThicknessProperty);
            set => base.SetValue(ImageCanvas.StrokeThicknessProperty, value);
        }

        #endregion

        #region 填充颜色 —— Brush Fill

        /// <summary>
        /// 填充颜色依赖属性
        /// </summary>
        public static DependencyProperty FillProperty;

        /// <summary>
        /// 填充颜色
        /// </summary>s
        public Brush Fill
        {
            get => (Brush)base.GetValue(ImageCanvas.FillProperty);
            set => base.SetValue(ImageCanvas.FillProperty, value);
        }

        #endregion

        #region 选中颜色 —— Brush SelectedColor

        /// <summary>
        /// 选中颜色依赖属性
        /// </summary>
        public static DependencyProperty SelectedShapeColorProperty;

        /// <summary>
        /// 默认选中的颜色
        /// </summary>s
        public Brush SelectedShapeColor
        {
            get => (Brush)base.GetValue(ImageCanvas.SelectedShapeColorProperty);
            set => base.SetValue(ImageCanvas.SelectedShapeColorProperty, value);
        }

        #endregion

        #region 型状右键菜单 —— ContextMenu ShapeContextMenu

        /// <summary>
        /// 型状右键菜单依赖属性
        /// </summary>
        public static DependencyProperty ShapeContextMenuProperty;

        /// <summary>
        /// 型状右键菜单
        /// </summary>
        public ContextMenu ShapeContextMenu
        {
            get => (ContextMenu)base.GetValue(ImageCanvas.ShapeContextMenuProperty);
            set => base.SetValue(ImageCanvas.ShapeContextMenuProperty, value);
        }

        #endregion

        #region 形状列表 —— ObservableCollection<ShapeX> ShapesProperty

        /// <summary>
        /// 形状列表依赖属性
        /// </summary>
        public static DependencyProperty ShapesProperty;

        /// <summary>
        /// 形状列表
        /// </summary>s
        public ObservableCollection<ShapeX> Shapes
        {
            get => (ObservableCollection<ShapeX>)base.GetValue(ImageCanvas.ShapesProperty);
            set => base.SetValue(ImageCanvas.ShapesProperty, value);
        }

        #endregion

        #region 选中的型状 —— ShapeX SelectedShape

        /// <summary>
        /// 选中的型状依赖属性
        /// </summary>
        public static DependencyProperty SelectedShapeProperty;

        /// <summary>
        /// 选中的型状
        /// </summary>s
        public ShapeX SelectedShape
        {
            get => (ShapeX)base.GetValue(ImageCanvas.SelectedShapeProperty);
            set => base.SetValue(ImageCanvas.SelectedShapeProperty, value);
        }

        #endregion

        #region 工具栏显示状态 —— bool ShowToolBar
        /// <summary>
        /// 工具栏显示状态依赖属性
        /// </summary>
        public static DependencyProperty ShowToolBarProperty;

        /// <summary>
        /// 工具栏显示状态
        /// </summary>s
        public bool ShowToolBar
        {
            get => (bool)base.GetValue(ImageCanvas.ShowToolBarProperty);
            set => base.SetValue(ImageCanvas.ShowToolBarProperty, value);
        }
        #endregion

        #region 是否可绘制矩形 —— bool IsCanDrawRectangle
        /// <summary>
        /// 是否可绘制矩形依赖属性
        /// </summary>
        public static DependencyProperty IsCanDrawRectangleProperty;

        /// <summary>
        /// 是否可绘制矩形
        /// </summary>s
        public bool IsCanDrawRectangle
        {
            get => (bool)base.GetValue(ImageCanvas.IsCanDrawRectangleProperty);
            set => base.SetValue(ImageCanvas.IsCanDrawRectangleProperty, value);
        }
        #endregion

        #region 是否可绘制圆形 —— bool IsCanDrawCircle
        /// <summary>
        /// 是否可绘制圆形依赖属性
        /// </summary>
        public static DependencyProperty IsCanDrawCircleProperty;

        /// <summary>
        /// 是否可绘制圆形
        /// </summary>s
        public bool IsCanDrawCircle
        {
            get => (bool)base.GetValue(ImageCanvas.IsCanDrawCircleProperty);
            set => base.SetValue(ImageCanvas.IsCanDrawCircleProperty, value);
        }
        #endregion

        #region 是否可绘制多边形 —— bool IsCanDrawPolygon
        /// <summary>
        /// 是否可绘制多边形依赖属性
        /// </summary>
        public static DependencyProperty IsCanDrawPolygonProperty;

        /// <summary>
        /// 是否可绘制多边形
        /// </summary>s
        public bool IsCanDrawPolygon
        {
            get => (bool)base.GetValue(ImageCanvas.IsCanDrawPolygonProperty);
            set => base.SetValue(ImageCanvas.IsCanDrawPolygonProperty, value);
        }
        #endregion

        #region 是否可绘制多线段 —— bool IsCanDrawPolyline
        /// <summary>
        /// 是否可绘制多线段依赖属性
        /// </summary>
        public static DependencyProperty IsCanDrawPolylineProperty;

        /// <summary>
        /// 是否可绘制多线段
        /// </summary>s
        public bool IsCanDrawPolyline
        {
            get => (bool)base.GetValue(ImageCanvas.IsCanDrawPolylineProperty);
            set => base.SetValue(ImageCanvas.IsCanDrawPolylineProperty, value);
        }
        #endregion

        #endregion

        #region # 回调方法

        #region 使用模式改变回调方法 —— static void OnUseModelChanged(DependencyObject dependencyObject...
        /// <summary>
        /// 使用模式改变回调方法
        /// </summary>
        private static void OnUseModelChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs eventArgs)
        {
            ImageCanvas that = (ImageCanvas)dependencyObject;
            CanvasUseMode oldValue = (CanvasUseMode)eventArgs.OldValue;
            CanvasUseMode newValue = (CanvasUseMode)eventArgs.NewValue;

            that.AppendElementByUseModel(oldValue, newValue);
        }
        #endregion

        #region 操作模式改变回调方法 —— static void OnOperatorModelChanged(DependencyObject dependencyObject...
        /// <summary>
        /// 操作模式改变回调方法
        /// </summary>
        private static void OnOperatorModelChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs eventArgs)
        {
            ImageCanvas that = (ImageCanvas)dependencyObject;
            CanvasOperatorMode newValue = (CanvasOperatorMode)eventArgs.NewValue;

            that.OperatorModelChanged(newValue);
        }
        #endregion

        #region 绘制类型改变回调方法 —— static void OnDrawTypeChanged(DependencyObject dependencyObject...
        /// <summary>
        /// 绘制类型改变回调方法
        /// </summary>
        private static void OnDrawTypeChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs eventArgs)
        {
            ImageCanvas that = (ImageCanvas)dependencyObject;
            CanvasShapeType newValue = (CanvasShapeType)eventArgs.NewValue;

            if (that.OperatorModel != CanvasOperatorMode.Draw)
                return;

            switch (newValue)
            {
                case CanvasShapeType.Rectangle:
                    that.OnToolbarOperatorModelClick(that.TBtnRectangle, null);
                    break;
                case CanvasShapeType.Circle:
                    that.OnToolbarOperatorModelClick(that.TBtnCircle, null);
                    break;
                case CanvasShapeType.Polygon:
                    that.OnToolbarOperatorModelClick(that.TBtnPolygon, null);
                    break;
                case CanvasShapeType.Polyline:
                    that.OnToolbarOperatorModelClick(that.TBtnPolyline, null);
                    break;
            }
        }
        #endregion

        #region 形状列表改变回调方法 —— static void OnShapesChanged(DependencyObject dependencyObject...
        /// <summary>
        /// 形状列表改变回调方法
        /// </summary>
        private static void OnShapesChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs eventArgs)
        {
            ImageCanvas that = (ImageCanvas)dependencyObject;

            if (that.Shapes == null)
                return;

            that.Shapes.CollectionChanged += that.OnShapesItemsChanged;
            that.RerenderShape(that.Shapes);
        }
        #endregion

        #region 形状列表元素改变回调方法 —— void OnShapesItemsChanged(object sender...
        /// <summary>
        /// 形状列表元素改变回调方法
        /// </summary>
        private void OnShapesItemsChanged(object sender, NotifyCollectionChangedEventArgs eventArgs)
        {
            if (this._isDraging)
                return;

            if (this.MainCanvas.Children.Count < 1)
                return;

            ObservableCollection<ShapeX> shapes = (ObservableCollection<ShapeX>)sender;
            this.RerenderShape(shapes);
        }
        #endregion

        #region 选中的形状改变回调方法 —— static void OnSelectedShapeChanged(DependencyObject dependencyObject...
        /// <summary>
        /// 选中的形状改变回调方法
        /// </summary>
        private static void OnSelectedShapeChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs eventArgs)
        {
            ImageCanvas that = (ImageCanvas)dependencyObject;
            ObservableCollection<CanvasShape> shapes = that._canvasShapes;
            that._oldShape = (ShapeX)eventArgs.OldValue;
            that._newShape = (ShapeX)eventArgs.NewValue;

            #region # 验证

            if (that._oldShape?.Name == that._newShape?.Name)
                return;

            #endregion

            // 设置原形状颜色
            if (that._oldShape != null)
            {
                CanvasShape canvasShape = shapes.SingleOrDefault(x => x.Name == that._oldShape.Name);
                if (canvasShape != null)
                {
                    canvasShape.Stroke = that._shapeOriginalColor!;
                    canvasShape.Fill = that._shapeOriginalFill!;
                    canvasShape.StrokeThickness = that._shapeOriginalThickness;
                }
            }

            // 设置新形状颜色
            if (that._newShape != null)
            {
                CanvasShape canvasShape = shapes.SingleOrDefault(x => x.Name == that._newShape.Name);
                if (canvasShape != null)
                {
                    // 设置原始颜色
                    that._shapeOriginalColor = canvasShape.Stroke;
                    that._shapeOriginalFill = canvasShape.Fill;
                    that._shapeOriginalThickness = canvasShape.StrokeThickness;

                    // 设置选中颜色
                    canvasShape.Stroke = that.SelectedShapeColor;
                    Color color = ((SolidColorBrush)that.SelectedShapeColor).Color;
                    color.A = 150;

                    canvasShape.SetValue(CanvasShape.FillProperty, new SolidColorBrush(color));

                    // TODO 多边形实现拖拽后 删除多边形、多线段判断条件
                    if (that.OperatorModel == CanvasOperatorMode.Drag && canvasShape.ShapeType != CanvasShapeType.Polygon && canvasShape.ShapeType != CanvasShapeType.Polyline)
                    {
                        canvasShape.ShapeElement.SetValue(DraggableControl.IsEditableProperty, true);
                        canvasShape.ShapeElement.SetValue(DraggableControl.IsSelectableProperty, true);
                        that._mainCanvasDraggable.TargetElement = canvasShape.ShapeElement;
                    }
                    else
                    {
                        canvasShape.ShapeElement.SetValue(DraggableControl.IsEditableProperty, false);
                        canvasShape.ShapeElement.SetValue(DraggableControl.IsSelectableProperty, false);
                        that._mainCanvasDraggable.SetValue(DraggableControl.TargetElementProperty, null);
                    }
                }
            }
            else
            {
                if (that.OperatorModel == CanvasOperatorMode.Drag)
                    that._mainCanvasDraggable.SetValue(DraggableControl.TargetElementProperty, null);
            }

            // 挂起路由事件
            that.RaiseEvent(new SelectedCanvasShapeChangedEventArgs(ImageCanvas._SelectedShapeChangedEvent, that, that._newShape));
        }
        #endregion

        #region 图片源改变回调方法 —— static void OnImageSourceChanged(DependencyObject dependencyObject...
        /// <summary>
        /// 图片源改变回调方法
        /// </summary>
        private static void OnImageSourceChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs eventArgs)
        {
            ImageCanvas that = (ImageCanvas)dependencyObject;
            that.MainImage.Source = that.ImageSource;

            that.UpdateScale();
        }
        #endregion

        #region 工具栏显示状态变回调方法 —— static void ShowToolBarChangedCallback(DependencyObject dependencyObject...
        /// <summary>
        /// 工具栏显示状态变回调方法
        /// </summary>
        private static void ShowToolBarChangedCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs eventArgs)
        {
            ImageCanvas that = (ImageCanvas)dependencyObject;
            bool newValue = (bool)eventArgs.NewValue;


            that.ToolBarBackground.Visibility = newValue ? Visibility.Visible : Visibility.Collapsed;
            that.ToolBarContainer.Visibility = newValue ? Visibility.Visible : Visibility.Collapsed;
        }
        #endregion

        #region 是否可绘制矩形变回调方法 —— static void IsCanDrawRectangleChangedCallback(DependencyObject dependencyObject...
        /// <summary>
        /// 是否可绘制矩形变回调方法
        /// </summary>
        private static void IsCanDrawRectangleChangedCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs eventArgs)
        {
            ImageCanvas that = (ImageCanvas)dependencyObject;
            bool newValue = (bool)eventArgs.NewValue;

            that.TBtnRectangle.Visibility = newValue ? Visibility.Visible : Visibility.Collapsed;
        }
        #endregion

        #region 是否可绘制圆形变回调方法 —— static void IsCanDrawCircleChangedCallback(DependencyObject dependencyObject...
        /// <summary>
        /// 是否可绘制圆形变回调方法
        /// </summary>
        private static void IsCanDrawCircleChangedCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs eventArgs)
        {
            ImageCanvas that = (ImageCanvas)dependencyObject;
            bool newValue = (bool)eventArgs.NewValue;

            that.TBtnCircle.Visibility = newValue ? Visibility.Visible : Visibility.Collapsed;
        }
        #endregion

        #region 是否可绘制多边形变回调方法 —— static void IsCanDrawPolygonChangedCallback(DependencyObject dependencyObject...
        /// <summary>
        /// 是否可绘制多边形变回调方法
        /// </summary>
        private static void IsCanDrawPolygonChangedCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs eventArgs)
        {
            ImageCanvas that = (ImageCanvas)dependencyObject;
            bool newValue = (bool)eventArgs.NewValue;

            that.TBtnPolygon.Visibility = newValue ? Visibility.Visible : Visibility.Collapsed;
        }
        #endregion

        #region 是否可绘制多线段变回调方法 —— static void IsCanDrawPolylineChangedCallback(DependencyObject dependencyObject...
        /// <summary>
        /// 是否可绘制多线段变回调方法
        /// </summary>
        private static void IsCanDrawPolylineChangedCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs eventArgs)
        {
            ImageCanvas that = (ImageCanvas)dependencyObject;
            bool newValue = (bool)eventArgs.NewValue;

            that.TBtnPolyline.Visibility = newValue ? Visibility.Visible : Visibility.Collapsed;
        }
        #endregion

        #endregion

        #region # 路由事件

        #region 型状绘制完成路由事件 —— RoutedEvent ShapeDrawn

        /// <summary>
        /// 型状绘制完成路由事件
        /// </summary>
        private static readonly RoutedEvent _ShapeDrawnEvent;

        /// <summary>
        /// 型状绘制完成路由事件处理程序
        /// </summary>
        public event RoutedEventHandler ShapeDrawn
        {
            add => base.AddHandler(ImageCanvas._ShapeDrawnEvent, value);
            remove => base.RemoveHandler(ImageCanvas._ShapeDrawnEvent, value);
        }

        #endregion

        #region 选中的型状改变路由事件 —— RoutedEvent SelectedShapeChanged

        /// <summary>
        /// 选中的型状改变路由事件
        /// </summary>
        private static readonly RoutedEvent _SelectedShapeChangedEvent;

        /// <summary>
        /// 选中的型状改变路由事件处理程序
        /// </summary>
        public event RoutedEventHandler SelectedShapeChanged
        {
            add => base.AddHandler(ImageCanvas._SelectedShapeChangedEvent, value);
            remove => base.RemoveHandler(ImageCanvas._SelectedShapeChangedEvent, value);
        }

        #endregion

        #region 型状点击路由事件 —— RoutedEvent ShapeClick

        /// <summary>
        /// 型状点击路由事件
        /// </summary>
        private static readonly RoutedEvent _ShapeClickEvent;

        /// <summary>
        /// 型状点击路由事件处理程序
        /// </summary>
        public event RoutedEventHandler ShapeClick
        {
            add => base.AddHandler(ImageCanvas._ShapeClickEvent, value);
            remove => base.RemoveHandler(ImageCanvas._ShapeClickEvent, value);
        }

        #endregion

        #region 型状拖拽改变路由事件 —— RoutedEvent ShapeDragChanging

        /// <summary>
        /// 型状拖拽改变路由事件
        /// </summary>
        private static readonly RoutedEvent _ShapeDragChangingEvent;

        /// <summary>
        /// 型状拖拽改变路由事件处理程序
        /// </summary>
        public event RoutedEventHandler ShapeDragChanging
        {
            add => base.AddHandler(ImageCanvas._ShapeDragChangingEvent, value);
            remove => base.RemoveHandler(ImageCanvas._ShapeDragChangingEvent, value);
        }

        #endregion

        #region 型状拖拽完成路由事件 —— RoutedEvent ShapeDragCompleted

        /// <summary>
        /// 型状拖拽完成路由事件
        /// </summary>
        private static readonly RoutedEvent _ShapeDragCompletedEvent;

        /// <summary>
        /// 型状拖拽完成路由事件处理程序
        /// </summary>
        public event RoutedEventHandler ShapeDragCompleted
        {
            add => base.AddHandler(ImageCanvas._ShapeDragCompletedEvent, value);
            remove => base.RemoveHandler(ImageCanvas._ShapeDragCompletedEvent, value);
        }

        #endregion

        #endregion

        #region # 事件处理程序

        #region 画布鼠标左键按下事件 —— void OnCanvasMouseLeftButtonDown(object sender...
        /// <summary>
        /// 画布鼠标左键按下事件
        /// </summary>
        private void OnCanvasMouseLeftButtonDown(object sender, MouseButtonEventArgs eventArgs)
        {
            #region # 验证

            if (this.ImageSource == null)
            {
                return;
            }

            #endregion

            if (eventArgs.OriginalSource is Canvas)
                this.SelectedShape = null;

            if (this.OperatorModel != CanvasOperatorMode.Draw)
                return;

            this._isDrawing = true;

            this._startPoint = eventArgs.GetPosition(this.MainCanvas).ToPointX();

            string shapeName;
            Random random = new Random();
            while (true)
            {
                string randomValue = random.Next(0, 100).ToString().PadLeft(3, '0');
                shapeName = $"Shape{this.Shapes.Count + 1}_{randomValue}";

                if (this.Shapes.Any(i => i.Name == shapeName))
                    continue;

                break;
            }

            CanvasShape canvasShape = this.AppendCanvasShape(this.DrawType, shapeName);
            canvasShape.Draw(this._startPoint);

            this.MainCanvas.MouseLeftButtonDown -= this.OnCanvasMouseLeftButtonDown;
        }
        #endregion

        #region 形状组件绘制完成事件 —— void OnShapeDrawn(object sender, CanvasShapeDrawnEventArgs eventArgs)
        /// <summary>
        /// 形状组件绘制完成事件
        /// </summary>
        private void OnShapeDrawn(object sender, CanvasShapeElementDrawnEventArgs eventArgs)
        {
            ShapeX shape = this.GetShapeX(eventArgs.Shape);

            CanvasShapeDrawnEventArgs args = new CanvasShapeDrawnEventArgs(ImageCanvas._ShapeDrawnEvent, this, shape);
            this.RaiseEvent(args);

            if (args.IsCancel)
            {
                this._canvasShapes.Remove(eventArgs.Shape);
                eventArgs.IsCancel = true;
            }
            else
            {
                this.Shapes.Add(shape);
            }

            this._isDrawing = false;
            this.MainCanvas.MouseLeftButtonDown += this.OnCanvasMouseLeftButtonDown;
        }
        #endregion

        #region 形状组件绘制完成事件 —— void OnShapeDrawn(object sender, CanvasShapeElementDrawCancelEventArgs eventArgs)
        /// <summary>
        /// 形状组件绘制完成事件
        /// </summary>
        private void CanvasShape_ShapeDrawCancel(object sender, CanvasShapeElementDrawCancelEventArgs eventArgs)
        {
            this._isDrawing = false;
            this.MainCanvas.MouseLeftButtonDown += this.OnCanvasMouseLeftButtonDown;
        }
        #endregion

        #region 形状点击事件 —— void OnShapeClick(object sender, CanvasShapeElementClickEventArgs eventArgs)
        /// <summary>
        /// 形状点击事件
        /// </summary>
        private void OnShapeClick(object sender, CanvasShapeElementClickEventArgs eventArgs)
        {
            if (this.OperatorModel == CanvasOperatorMode.Draw)
                return;

            ShapeX shape = this.Shapes.Single(i => i.Name == eventArgs.Shape.Name);
            this.SelectedShape = shape;

            // 挂起路由事件
            this.RaiseEvent(new CanvasShapeClickEventArgs(ImageCanvas._ShapeClickEvent, this, this._oldShape, this._newShape));
        }
        #endregion

        #region 型状拖拽改变事件 —— void OnDragChanging(object sender, DraggedEventArgs eventArgs)
        /// <summary>
        /// 型状拖拽改变事件
        /// </summary>
        private void OnDragChanging(object sender, DraggedEventArgs eventArgs)
        {
            this._isDraging = true;

            DraggableControl draggedControl = (DraggableControl)sender;
            CanvasShape canvasShape = this._canvasShapes.SingleOrDefault(i => i.Name == this.SelectedShape.Name);
            canvasShape?.Drag(eventArgs);

            this._newShape = this.GetShapeX(canvasShape);

            for (int i = 0; i < this.Shapes.Count; i++)
            {
                if (this.Shapes[i].Name == this._newShape.Name)
                {
                    this.Shapes[i] = this._newShape;
                }
            }

            this.RaiseEvent(new CanvasShapeDragChangingEventArgs(ImageCanvas._ShapeDragChangingEvent, this, this._newShape));
        }
        #endregion

        #region 型状拖拽完成事件 —— void OnDragCompleted(object sender...
        /// <summary>
        /// 型状拖拽完成事件
        /// </summary>
        private void OnDragCompleted(object sender, DraggedEventArgs eventArgs)
        {
            this._isDraging = false;

            this.SelectedShape = this._newShape;
            this.RaiseEvent(new CanvasShapeDragCompletedEventArgs(ImageCanvas._ShapeDragCompletedEvent, this, this._newShape));
        }
        #endregion

        #region 打开图片点击事件 —— void OnOpenImageClick(object sender...
        /// <summary>
        /// 打开图片点击事件
        /// </summary>
        private void OnOpenImageClick(object sender, RoutedEventArgs e)
        {

            OpenFileDialog openFileDialog = new OpenFileDialog
            {
                Filter = "图像文件(*.jpg;*.jpeg;*.png;*.gif;*.bmp;*.ico)|*.jpg;*.jpeg;*.png;*.gif;*.bmp;*.ico|所有文件(*.*)|*.*",
                AddExtension = true,
                RestoreDirectory = true
            };

            if (openFileDialog.ShowDialog() != true)
                return;

            BitmapImage bitmapImage = new BitmapImage(new Uri(openFileDialog.FileName));
            this.ImageSource = bitmapImage;
        }
        #endregion

        #region 查看图片点击事件 —— void OnOpenImageClick(object sender...
        /// <summary>
        /// 查看图片点击事件
        /// </summary>
        private void OnLookImageClick(object sender, RoutedEventArgs e)
        {
            Window lookImageWindow = new Window
            {
                WindowState = WindowState.Maximized,
                FontSize = 14,
                WindowStyle = WindowStyle.ThreeDBorderWindow,
                WindowStartupLocation = WindowStartupLocation.CenterScreen
            };

            Grid mainContent = new Grid();
            ImageViewer imageViewer = new ImageViewer
            {
                ImageSource = this.DrawImageShape()
            };
            mainContent.Children.Add(imageViewer);
            lookImageWindow.Content = mainContent;

            lookImageWindow.ShowDialog();
        }
        #endregion

        #region 工具栏操作模式点击事件 —— void OnToolbarOperatorModelClick(object sender...
        /// <summary>
        /// 工具栏操作模式点击事件
        /// </summary>
        private void OnToolbarOperatorModelClick(object sender, RoutedEventArgs e)
        {
            ToggleButton tbtn = (ToggleButton)sender;
            ShapeX oldShape = this.SelectedShape;

            // 重置其他按钮状态
            this.ResetOperatorModel();

            // 设置选中
            tbtn.IsChecked = true;

            if (tbtn == this.TBtnRectangle)
            {

                this.OperatorModel = CanvasOperatorMode.Draw;
                this.DrawType = CanvasShapeType.Rectangle;
            }
            else if (tbtn == this.TBtnPolygon)
            {
                this.OperatorModel = CanvasOperatorMode.Draw;
                this.DrawType = CanvasShapeType.Polygon;
            }
            else if (tbtn == this.TBtnCircle)
            {
                this.OperatorModel = CanvasOperatorMode.Draw;
                this.DrawType = CanvasShapeType.Circle;
            }
            else if (tbtn == this.TBtnPolyline)
            {
                this.OperatorModel = CanvasOperatorMode.Draw;
                this.DrawType = CanvasShapeType.Polyline;
            }
            else if (tbtn == this.TBtnDrag)
            {
                this.OperatorModel = CanvasOperatorMode.Drag;

                CanvasShape oldShapeElement = this._canvasShapes.SingleOrDefault(i => i.ShapeElement.Name == this.SelectedShape?.Name);
                oldShapeElement?.ShapeElement.SetValue(DraggableControl.IsEditableProperty, true);
                oldShapeElement?.ShapeElement.SetValue(DraggableControl.IsSelectableProperty, true);
                this._mainCanvasDraggable.SetValue(DraggableControl.TargetElementProperty, oldShapeElement?.ShapeElement);

                this.SelectedShape = oldShape;
            }
            else if (tbtn == this.TBtnNormal)
            {
                this.OperatorModel = CanvasOperatorMode.Nomal;
                this.SelectedShape = oldShape;
                foreach (CanvasShape canvasShape in this._canvasShapes)
                {
                    canvasShape.ContextMenu = this.ShapeContextMenu;
                }
            }

            this.SetCursor();
        }
        #endregion

        #endregion

        #region # 方法

        #region 渲染 —— void Render()
        /// <summary>
        /// 渲染
        /// </summary>
        private void Render()
        {
            // 图片画布拖拽组件
            this._mainCanvasDraggable = new DraggableControl
            {
                Name = "MainCanvasDraggable",
                CornerWidth = 10
            };
            this._mainCanvasDraggable.DragChanging += this.OnDragChanging;
            this._mainCanvasDraggable.DragCompleted += this.OnDragCompleted;
            this.MainCanvas.Children.Add(this._mainCanvasDraggable);

            this.AppendElementByUseModel(null, this.UseModel);
        }
        #endregion

        #region 重新渲染型状 —— void RerenderShape(ObservableCollection<ShapeX> shapes)
        /// <summary>
        /// 重新渲染型状
        /// </summary>
        /// <param name="shapes">型状集</param>
        private void RerenderShape(ObservableCollection<ShapeX> shapes)
        {

            if (!this.MainImage.IsLoaded)
            {
                this.MainImage.Loaded += (s, e) =>
                {
                    this.RerenderShape(shapes);
                };
                return;
            }

            this.UpdateScale();

            int count = this.MainCanvas.Children.Count - 1;
            this.MainCanvas.Children.RemoveRange(1, count);
            this._canvasShapes.Clear();

            //return;
            if (shapes == null)
                return;

            // 根据大小重新排序
            IEnumerable<ShapeX> orderlyShapes = shapes.OrderByDescending(i =>
            {
                int result = 0;
                switch (i)
                {
                    case RectangleX rectangleX:
                        result = rectangleX.Width > rectangleX.Height ? rectangleX.Width : rectangleX.Height;
                        break;
                    case PolygonX polygonX:
                        {
                            double minX = polygonX.Points.Min(j => j.X);
                            double maxX = polygonX.Points.Max(j => j.X);
                            double width = maxX - minX;
                            double minY = polygonX.Points.Min(j => j.Y);
                            double maxY = polygonX.Points.Max(j => j.Y);
                            double height = maxY - minY;

                            result = (int)(width > height ? width : height);
                            break;
                        }
                    case PolylineX polylineX:
                        {
                            double minX = polylineX.Points.Min(j => j.X);
                            double maxX = polylineX.Points.Max(j => j.X);
                            double width = maxX - minX;
                            double minY = polylineX.Points.Min(j => j.Y);
                            double maxY = polylineX.Points.Max(j => j.Y);
                            double height = maxY - minY;

                            result = (int)(width > height ? width : height);
                            break;
                        }
                    case CircleX circleX:
                        result = circleX.Radius;
                        break;
                }
                return result;
            }).ToList();

            // 重新绘制
            int zIndex = 10;
            int shapeIndex = 0;
            foreach (ShapeX shape in orderlyShapes)
            {
                CanvasShapeType drawType = shape switch
                {
                    RectangleX rectangleX => CanvasShapeType.Rectangle,
                    CircleX circleX => CanvasShapeType.Circle,
                    PolygonX polygonX => CanvasShapeType.Polygon,
                    PolylineX polylineX => CanvasShapeType.Polyline
                };


                string shapeName = string.IsNullOrWhiteSpace(shape.Name) ? $"Shape{shapeIndex}" : shape.Name;
                shape.Name = shapeName;

                int index = shapeName.IndexOf("_");

                if (index < 0)
                {
                    Random random = new Random();
                    string randomValue = random.Next(0, 100).ToString().PadLeft(3, '0');
                    shapeName += $"_{randomValue}";
                }

                CanvasShape canvasShape = this.AppendCanvasShape(drawType, shapeName);
                canvasShape.Text = shape.Text;
                canvasShape.Stroke = new SolidColorBrush(Color.FromRgb(shape.Stroke.R, shape.Stroke.G, shape.Stroke.B));
                canvasShape.StrokeThickness = shape.StrokeThickness;
                canvasShape.ZIndex = zIndex;
                canvasShape.Draw(this._scale, shape);
                canvasShape.ContextMenu = this.OperatorModel == CanvasOperatorMode.Nomal ? this.ShapeContextMenu : null;
                zIndex++;
                shapeIndex++;

                if (this.SelectedShape == null || this.SelectedShape.Name != shape.Name)
                    continue;

                this._shapeOriginalColor = canvasShape.Stroke;
                this._shapeOriginalThickness = canvasShape.StrokeThickness;

            }
            
            this.SetCursor();
        }
        #endregion

        #region 根据使用模式添加组件 —— void AppendElementByUseModel(ImageCanvasUseModel? oldUseModel...
        /// <summary>
        /// 根据使用模式添加组件
        /// </summary>
        /// <param name="oldUseModel">原使用模式</param>
        /// <param name="newUseModel">新使用模式</param>
        private void AppendElementByUseModel(CanvasUseMode? oldUseModel, CanvasUseMode newUseModel)
        {
            switch (newUseModel)
            {
                case CanvasUseMode.Nomal:
                    this.BtnOpenImage.Visibility = Visibility.Collapsed;
                    this.TBtnDrag.Visibility = Visibility.Collapsed;
                    this.TBtnRectangle.Visibility = Visibility.Collapsed;
                    this.TBtnPolygon.Visibility = Visibility.Collapsed;
                    this.TBtnCircle.Visibility = Visibility.Collapsed;
                    this.TBtnPolyline.Visibility = Visibility.Collapsed;
                    break;
                case CanvasUseMode.Edit:
                    this.BtnOpenImage.Visibility = Visibility.Visible;
                    this.TBtnDrag.Visibility = Visibility.Visible;
                    this.TBtnRectangle.Visibility = this.IsCanDrawRectangle ? Visibility.Visible : Visibility.Collapsed;
                    this.TBtnPolygon.Visibility = this.IsCanDrawPolygon ? Visibility.Visible : Visibility.Collapsed;
                    this.TBtnCircle.Visibility = this.IsCanDrawCircle ? Visibility.Visible : Visibility.Collapsed;
                    this.TBtnPolyline.Visibility = this.IsCanDrawPolyline ? Visibility.Visible : Visibility.Collapsed;
                    break;
            }

            this.OperatorModelChanged(CanvasOperatorMode.Nomal);
        }
        #endregion

        #region 操作模式改变 —— void OperatorModelChanged(ImageCanvasOperatorModel newValue)
        /// <summary>
        /// 操作模式改变
        /// </summary>
        /// <param name="newValue">新操作模式</param>
        private void OperatorModelChanged(CanvasOperatorMode newValue)
        {
            switch (newValue)
            {
                case CanvasOperatorMode.Nomal:
                    this.OnToolbarOperatorModelClick(this.TBtnNormal, null);
                    break;
                case CanvasOperatorMode.Drag:
                    this.OnToolbarOperatorModelClick(this.TBtnDrag, null);
                    break;
                case CanvasOperatorMode.Draw:
                    switch (this.DrawType)
                    {
                        case CanvasShapeType.Rectangle:
                            ImageCanvas.OnDrawTypeChanged(this, new DependencyPropertyChangedEventArgs(ImageCanvas.DrawTypeProperty, this.DrawType, CanvasShapeType.Rectangle));
                            break;
                        case CanvasShapeType.Circle:
                            ImageCanvas.OnDrawTypeChanged(this, new DependencyPropertyChangedEventArgs(ImageCanvas.DrawTypeProperty, this.DrawType, CanvasShapeType.Circle));
                            break;
                        case CanvasShapeType.Polygon:
                            ImageCanvas.OnDrawTypeChanged(this, new DependencyPropertyChangedEventArgs(ImageCanvas.DrawTypeProperty, this.DrawType, CanvasShapeType.Polygon));
                            break;
                        case CanvasShapeType.Polyline:
                            ImageCanvas.OnDrawTypeChanged(this, new DependencyPropertyChangedEventArgs(ImageCanvas.DrawTypeProperty, this.DrawType, CanvasShapeType.Polyline));
                            break;
                    }
                    break;
            }
        }
        #endregion

        #region 更新缩放系数 —— void UpdateScale()
        /// <summary>
        /// 更新缩放系数
        /// </summary>
        private void UpdateScale()
        {
            BitmapSource bitmapSource = (BitmapSource)this.MainImage.Source;

            if (bitmapSource == null)
            {
                this._scale = 0;
            }
            else
            {
                if (bitmapSource.IsDownloading)
                {
                    bitmapSource.DownloadCompleted += (s, e) =>
                    {
                        this.UpdateScale();
                    };
                    return;
                }

                if (!this.MainImage.IsLoaded)
                {
                    this.MainImage.Loaded += (s, e) =>
                    {
                        this.UpdateScale();
                    };
                    return;
                }

                this.UpdateLayout();

                double visualWidth = this.MainImage.ActualWidth;
                double visualHeight = this.MainImage.ActualHeight;
                double actualWidth = bitmapSource.PixelWidth;
                double actualHeight = bitmapSource.PixelHeight;
                this._scale = actualWidth >= actualHeight ? visualWidth / actualWidth : visualHeight / actualHeight;
            }

            // 设置只读依赖属性
            this.SetValue(ImageCanvas.ImageScalePropertyKey, this._scale);

        }
        #endregion

        #region 重置工具栏操作模式 —— void ResetOperatorModel()
        /// <summary>
        /// 重置工具栏操作模式
        /// </summary>
        private void ResetOperatorModel()
        {
            this.TBtnNormal.IsChecked = false;
            this.TBtnDrag.IsChecked = false;
            this.TBtnRectangle.IsChecked = false;
            this.TBtnPolygon.IsChecked = false;
            this.TBtnCircle.IsChecked = false;
            this.TBtnPolyline.IsChecked = false;
            this._isDraging = false;


            if (this._isDrawing)
            {
                CanvasShape canvasShape = this._canvasShapes?.LastOrDefault();
                canvasShape?.DrawCancel();

                this._isDrawing = false;
                this.MainCanvas.MouseLeftButtonDown += this.OnCanvasMouseLeftButtonDown;
            }

            if (this._canvasShapes != null)
            {
                foreach (CanvasShape canvasShape in this._canvasShapes)
                {
                    canvasShape.ShapeElement.SetValue(DraggableControl.IsEditableProperty, false);
                    canvasShape.ShapeElement.SetValue(DraggableControl.IsSelectableProperty, false);
                    canvasShape.ContextMenu = null;
                }
            }

            this._mainCanvasDraggable.SetValue(DraggableControl.TargetElementProperty, null);

            this.SelectedShape = null;
        }
        #endregion

        #region 绘制标记 —— ImageSource DrawImageShape()
        /// <summary>
        /// 绘制标记
        /// </summary>
        /// <returns></returns>
        private ImageSource DrawImageShape()
        {
            if (this.ImageSource == null)
                return null;

            BitmapSource bitmapSource = (BitmapSource)this.ImageSource;

            using SKBitmap bitmap = bitmapSource.ToSKBitmap();
            using SKCanvas canvas = new SKCanvas(bitmap);

            foreach (ShapeX shape in this.Shapes)
            {
                using SKPaint skPaint = new SKPaint
                {
                    Color = new SKColor(shape.Stroke.R, shape.Stroke.G, shape.Stroke.B, shape.Stroke.A),
                    Style = SKPaintStyle.Stroke,
                    StrokeWidth = (float)(1 / this._scale)
                };

                switch (shape)
                {
                    case RectangleX rectangle:

                        canvas.DrawRect(rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height, skPaint);

                        break;
                    case CircleX circle:

                        canvas.DrawCircle(circle.X, circle.Y, circle.Radius, skPaint);

                        float lineLight = 5f / (float)this._scale;
                        canvas.DrawLine(circle.X - lineLight, circle.Y, circle.X + lineLight, circle.Y, skPaint);
                        canvas.DrawLine(circle.X, circle.Y - lineLight, circle.X, circle.Y + lineLight, skPaint);

                        break;
                    case PolygonX polygon:

                        List<SKPoint> polygonPoints = polygon.Points.Select(i => i.ToSkPoint()).ToList();
                        polygonPoints.Add(polygonPoints.First());

                        canvas.DrawPoints(SKPointMode.Polygon, polygonPoints.ToArray(), skPaint);

                        break;
                    case PolylineX polyline:

                        PointX[] polylinePoints = polyline.Points.ToArray();

                        for (int i = 0; i < polylinePoints.Length; i++)
                        {
                            PointX polylinePoint = polylinePoints[i];
                            if (polylinePoint == polylinePoints.Last())
                                break;

                            PointX polylinePointNext = polylinePoints[i + 1];

                            canvas.DrawLine((float)polylinePoint.X, (float)polylinePoint.Y, (float)polylinePointNext.X, (float)polylinePointNext.Y, skPaint);
                        }

                        break;
                }
            }
            ImageSource result = bitmap.ToWriteableBitmap();

            return result;
        }
        #endregion

        #region 添加画布形状 —— CanvasShape AppendCanvasShape(CanvasShapeType drawType, int index)
        /// <summary>
        /// 添加画布形状
        /// </summary>
        /// <param name="drawType">型状类型</param>
        /// <param name="shapeName">型状名称</param>
        /// <returns>画布形状</returns>
        private CanvasShape AppendCanvasShape(CanvasShapeType drawType, string shapeName)
        {
            CanvasShape canvasShape = drawType switch
            {
                CanvasShapeType.Rectangle => new CanvasRectangle(),
                CanvasShapeType.Circle => new CanvasCircle(),
                CanvasShapeType.Polygon => new CanvasPolygon(),
                CanvasShapeType.Polyline => new CanvasPolyline(),
            };

            int index = shapeName.IndexOf("_");

            if (index < 0)
            {
                Random random = new Random();
                string randomValue = random.Next(0, 100).ToString().PadLeft(3, '0');
                shapeName += $"_{randomValue}";
            }

            canvasShape.Name = shapeName;
            canvasShape.Stroke = this.Stroke;
            canvasShape.StrokeThickness = this.StrokeThickness;
            canvasShape.Fill = this.Fill;
            canvasShape.FontSize = 14;
            canvasShape.ShapeClick += this.OnShapeClick;
            canvasShape.ShapeDrawn += this.OnShapeDrawn;
            canvasShape.ShapeDrawCancel += CanvasShape_ShapeDrawCancel; ;
            canvasShape.ShapeElement.SetValue(DraggableControl.IsEditableProperty, false);
            canvasShape.ShapeElement.SetValue(DraggableControl.IsSelectableProperty, false);
            this.MainCanvas.Children.Add(canvasShape);
            this._canvasShapes.Add(canvasShape);

            return canvasShape;
        }
        #endregion

        #region 获取形状X —— ShapeX GetShapeX(CanvasShape canvasShape)
        /// <summary>
        /// 获取形状X
        /// </summary>
        /// <param name="canvasShape">画布形状</param>
        /// <returns>形状X</returns>
        private ShapeX GetShapeX(CanvasShape canvasShape)
        {
            ShapeX shape = null;

            switch (canvasShape)
            {
                case CanvasRectangle canvasRectangle:
                    {
                        int x = (int)Math.Round(canvasRectangle.X / this._scale);
                        int y = (int)Math.Round(canvasRectangle.Y / this._scale);
                        int w = (int)Math.Round(canvasRectangle.Width / this._scale);
                        int h = (int)Math.Round(canvasRectangle.Height / this._scale);

                        shape = new RectangleX(canvasRectangle.Name, x, y, w, h);
                        shape.Tag = canvasShape.Tag;
                        break;
                    }
                case CanvasCircle canvasCircle:
                    {
                        int x = (int)Math.Round(canvasCircle.X / this._scale);
                        int y = (int)Math.Round(canvasCircle.Y / this._scale);
                        int radius = (int)Math.Round(canvasCircle.Radius / this._scale);

                        shape = new CircleX(canvasCircle.Name, x, y, radius);
                        shape.Tag = canvasShape.Tag;
                        break;
                    }
                case CanvasPolygon canvasPolygon:
                    {
                        IEnumerable<PointX> points = canvasPolygon.Points.ToList();

                        shape = new PolygonX(canvasPolygon.Name, points);
                        shape.Tag = canvasShape.Tag;
                        break;
                    }
                case CanvasPolyline canvasPolyline:
                    {
                        IEnumerable<PointX> points = canvasPolyline.Points.ToList();

                        shape = new PolylineX(canvasPolyline.Name, points);
                        shape.Tag = canvasShape.Tag;
                        break;
                    }
            }

            return shape;
        }
        #endregion

        #region 设置光标 —— void SetCursor()
        /// <summary>
        /// 设置光标
        /// </summary>
        private void SetCursor()
        {
            if (this.OperatorModel == CanvasOperatorMode.Draw)
            {
                foreach (CanvasShape canvasShape in this._canvasShapes)
                {
                    canvasShape.Cursor = Cursors.Pen;
                }

                this.MainCanvas.Cursor = Cursors.Pen;
            }
            else
            {
                foreach (CanvasShape canvasShape in this._canvasShapes)
                {
                    canvasShape.Cursor = Cursors.Hand;
                }
                this.MainCanvas.Cursor = Cursors.Arrow;
            }
        }
        #endregion

        #endregion

    }
}